/***********************************************************************************************/ /**
*\n  @file       app_can.c
*\n  @brief      app_can模块,主文件
*\n  @details
*\n -----------------------------------------------------------------------------------
*\n  文件说明：
*\n       1. app_can模块, 启动接口
*\n
*\n -----------------------------------------------------------------------------------
*\n  版本:    修改人:       修改日期:          描述:
*\n  V0.01  罗先能        2021.5.10      创建
*\n
***************************************************************************************************/

/**************************************************************************************************
* 头文件
***************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>

#include "hal.h"
#include "app_rs232.h"

#undef   DEBUG_LEVEL
#define  DEBUG_LEVEL  5   // 定义debug级别 (0 ~ 5)
#include "vdebug.h"

/**************************************************************************************************
* 宏定义、结构定义
***************************************************************************************************/



/**************************************************************************************************
* 全局变量声明、定义
***************************************************************************************************/


/**************************************************************************************************
* 私有变量声明、定义
***************************************************************************************************/
static TRs232Handle tHandle1 =
{
	.iBandrate = 115200, // 波特率
	.iStopBit = 1,		 // 停止位 1==1bit, 2==2bit(or 1.5bit)
};

/**************************************************************************************************
* 私有函数声明、定义
***************************************************************************************************/

#if 0
/****************************************************************
* Constants
****************************************************************/
#define SYSFS_GPIO_DIR    "/sys/class/gpio"
#define POLL_TIMEOUT      (2 * 1000)             /* 2 seconds */
#define MAX_BUF           64

/****************************************************************
 * gpio_export
 ****************************************************************/
static int gpio_export(unsigned int gpio)
{
	int fd, len;
	char buf[MAX_BUF];

	fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
	if (fd < 0)
	{
		perror("gpio/export");
		return fd;
	}

	len = snprintf(buf, sizeof(buf), "%d", gpio);
	write(fd, buf, len);
	close(fd);

	return 0;
}

/****************************************************************
 * gpio_unexport
 ****************************************************************/
static int gpio_unexport(unsigned int gpio)
{
	int fd, len;
	char buf[MAX_BUF];

	fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);
	if (fd < 0)
	{
		perror("gpio/export");
		return fd;
	}

	len = snprintf(buf, sizeof(buf), "%d", gpio);
	write(fd, buf, len);
	close(fd);
	return 0;
}

/****************************************************************
 * gpio_set_dir
 ****************************************************************/
static int gpio_set_dir(unsigned int gpio, unsigned int out_flag)
{
	int fd, len;
	char buf[MAX_BUF];

	len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", gpio);

	fd = open(buf, O_WRONLY);
	if (fd < 0)
	{
		perror("gpio/direction");
		return fd;
	}

	if (out_flag)
		write(fd, "out", 4);
	else
		write(fd, "in", 3);

	close(fd);
	return 0;
}

/****************************************************************
 * gpio_set_value
 ****************************************************************/
static int gpio_set_value(unsigned int gpio, unsigned int value)
{
	int fd, len;
	char buf[MAX_BUF];

	len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

	fd = open(buf, O_WRONLY);
	if (fd < 0)
	{
		perror("gpio/set-value");
		return fd;
	}

	if (value)
		write(fd, "1", 2);
	else
		write(fd, "0", 2);

	close(fd);
	return 0;
}

/****************************************************************
 * gpio_get_value
 ****************************************************************/
static int gpio_get_value(unsigned int gpio, unsigned int *value)
{
	int fd, len;
	char buf[MAX_BUF];
	char ch;

	len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

	fd = open(buf, O_RDONLY);
	if (fd < 0)
	{
		perror("gpio/get-value");
		return fd;
	}

	read(fd, &ch, 1);

	if (ch != '0')
	{
		*value = 1;
	}
	else
	{
		*value = 0;
	}

	close(fd);
	return 0;
}


/****************************************************************
 * gpio_set_edge
 ****************************************************************/
static int gpio_set_edge(unsigned int gpio, char *edge)
{
	int fd, len;
	char buf[MAX_BUF];

	len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);

	fd = open(buf, O_WRONLY);
	if (fd < 0)
	{
		perror("gpio/set-edge");
		return fd;
	}

	write(fd, edge, strlen(edge) + 1);
	close(fd);
	return 0;
}

/****************************************************************
 * gpio_fd_open
 ****************************************************************/
static int gpio_fd_open(unsigned int gpio)
{
	int fd, len;
	char buf[MAX_BUF];

	len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

	fd = open(buf, O_RDONLY | O_NONBLOCK);
	if (fd < 0)
	{
		perror("gpio/fd_open");
	}
	return fd;
}

/****************************************************************
 * gpio_fd_close
 ****************************************************************/
static int gpio_fd_close(int fd)
{
	return close(fd);
}




static void usage(char *name)
{
	printf("\n");
	printf("Usage:\n");
	printf("read: %s  <gpio-pin-num>\n", name);
	printf("  Waits for a change in the GPIO pin voltage\n");

	printf("\n");
}



/**************************************************************************************************
* 全局函数声明、定义
***************************************************************************************************/

// ---------------测试gpio中断 --------------
int AppRs232Start(int argc, char *argv[])
{

	/*
	首先需要将该gpio(Mio39)配置为中断,
	echo "945" > /sys/class/gpio/export
	echo "in" > /sys/class/gpio/gpio945/direction
	echo "falling" > /sys/class/gpio/gpio945/edge
	# echo "rising" > /sys/class/gpio/gpio945/edge

	以下是伪代码:
	注意: 使用poll()函数，设置事件监听类型为POLLPRI和POLLERR在poll()返回后，
	使用lseek()移动到文件开头读取新的值或者关闭它再重新打开读取新值。
	必须这样做否则poll函数会总是返回。
	*/

	struct pollfd fdset[2];
	int nfds;
	int gpio_fd;
	int timeout;
	int rc, ret;
	char *buf[MAX_BUF];
	unsigned int gpio;
	int len;



	if (argc < 2)
	{
		usage(argv[0]);
		return (-1);
	}

	gpio = atoi(argv[1]);

	gpio_export(gpio);
	gpio_set_dir(gpio, 0);  // 0=input,1=output
	gpio_set_edge(gpio, "falling");
	gpio_fd = gpio_fd_open(gpio);
	if (gpio_fd == -1)
    {
        debug_error("gpio_fd_open() \n");
        return -1;
    }

    read(gpio_fd, buf, sizeof(buf));  // fixbug: 第一次为有效值,清除中断;
	while (1)
	{
		memset((void *)fdset, 0, sizeof(fdset));
		fdset[0].fd = gpio_fd;
		fdset[0].events = POLLPRI;
		nfds = 1;
		timeout = POLL_TIMEOUT;
		ret = poll(fdset, nfds, timeout);
		if (ret < 0)
		{
			debug_error("poll() \n");
			continue;
		}
		else if (ret == 0)
		{
			printf(".");
			fflush(stdout);
			continue;
		}

        if (fdset[0].revents & POLLPRI)
        {
            ret = lseek(gpio_fd, 0, SEEK_SET);
            if (ret == -1)
            {
                debug_error("lseek \n");
                continue;
            }

            memset(buf, 0, sizeof(buf));
            ret = read(gpio_fd, buf, 10);
            if (ret == -1)
            {
                debug_error("read \n");
                continue;
            }

            /* 此时表示已经监听到中断触发了 */
            printf("io=%s\n", buf);
        }


	}

	gpio_fd_close(gpio_fd);
	return 0;
}
#endif

#if 0
// ---------------测试gpio中断 --------------
int AppRs232Start(int argc, char *argv[])
{
	int ret = HwOpen(DEV_NO_GPIO39, NULL);
	if (ret == -1)
    {
        debug_error("HwOpen() \n");
        return -1;
    }

	while (1)
	{
		ret = HwRead(DEV_NO_GPIO39, null, NULL, null);  //阻塞,等待gpio中断
		if(ret < 0)
		{	// error
			continue;
		}
		else if(ret == 0)
		{  // timeout
			continue;
		}

        /* 此时表示已经监听到中断触发了 */
	}

	HwClose(DEV_NO_GPIO39, NULL);
	return 0;
}
#endif


#if 0
// ---------------测试spi  驱动读写操作 --------------
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>

#define SC752A "/dev/spi2uart0"
#define SC752B "/dev/spi2uart1"


#define SET_channleA 	_IOW('k', 0, int)
#define SET_channleB 	_IOW('k', 1, int)
#define SET_STOP_BIT 	_IOW('k', 2, int)
#define SET_BPS 		_IOW('k', 3, int)

#define STOP_BIT_1 		0x01
#define STOP_BIT_2 		0x02
/**************************************************/
/*  说明：sc16is752可以设置1 1.5 2 位停止位，默认设置为1个停止位，字长度默认为8，且不可修改 */
/*  默认波特率设置为9600  */
/*  0-1个停止位（字长度=5，6，7，8） */
/*  1.5个停止位（字长度=5）*/
/*  2个停止位 */
/**************************************************/


static void usage(char *name)
{
	printf("\n");
	printf("Usage:\n");
	printf("send : %s wr <channel> <bandrate> <string>\n", name);
	printf("recv : %s rd <channel> <bandrate>         \n", name);
	printf("set :  %s set <channel> <stopbit>         \n", name);
	printf("\n");
}


int main(int argc, char *argv[])
{
	#define BUFFER_MAX_SIZE  (4*1024)

	long channel = 0;
	long bandtate = 9600;
	long stopbit = STOP_BIT_1;
	char buf[BUFFER_MAX_SIZE] = {0};
	int length = 0;
	int i = 0;
	char c;

	if (argc < 4)
	{
		usage(argv[0]);
		return -1;
	}
	else if (strcmp(argv[1],  "wr") == 0)
	{
		/* 发送测试 -------------------------------------- */
		/* 默认是通道A，波特率9600，停止位1位 */
		if (argc != 5)
		{
			usage(argv[0]);
			return -1;
		}

		int fd = open(SC752A, O_RDWR);
		if (fd < 0)
		{
			printf("Open %s failure.\n", SC752A);
			return -1;
		}

		channel = atoi(argv[2]);
		bandtate = atoi(argv[3]);
		ioctl(fd, SET_BPS, bandtate);
		ioctl(fd, SET_STOP_BIT, STOP_BIT_1);


		length = strlen(argv[4]);
		memset(buf, 0, sizeof(buf));
		memcpy(buf, argv[4], length);
		buf[length] = '\n';
		write(fd, buf, length+1);
		usleep(1000*50);
		close(fd);
	}
	else if (strcmp(argv[1],  "rd") == 0)
	{
		/* 接收测试 ------------------------------------- */
		int fd = open(SC752A, O_RDWR);
		if (fd < 0)
		{
			printf("Open %s failure.\n", SC752A);
			return -1;
		}

		channel = atoi(argv[2]);

		bandtate = atoi(argv[3]);
		ioctl(fd, SET_BPS, bandtate);
		while (1)
		{
			memset(buf, 0, sizeof(buf));
			length = read(fd, buf, 30);
			if (length > 0)
			{
				printf("%s\n", buf);
			}
			usleep(1000*50);
		}
		close(fd);
	}
	else if (strcmp(argv[1],  "set") == 0)
	{
		int fd = open(SC752A, O_RDWR);
		if (fd < 0)
		{
			printf("Open %s failure.\n", SC752A);
			return -1;
		}

		channel = atoi(argv[2]);
		stopbit = atoi(argv[3]);
		stopbit = (stopbit == STOP_BIT_2) ? STOP_BIT_2 : STOP_BIT_1;
		ioctl(fd, SET_STOP_BIT, stopbit);

		usleep(1);
		printf("set channel %d  %d stopbit\n", channel, stopbit);
		close(fd);
	}
	return 0;
}
#endif


#if 1
static void usage(char *name)
{
	printf("\n");
	printf("Usage:\n");
	printf("send : %s wr <channel> <bandrate> <stopbit> <string>\n", name);
	printf("recv : %s rd <channel> <bandrate> <stopbit>         \n", name);
	printf("<channel> bit[0]:1=enable channel0, bit[1]:1=enable channel1 \n");
	printf("\n");
}

// 接收线程
void* UartRecvTask(void *arg)
{
	char buffer[128];
	int channel = (int)arg;
	int iNo = (channel == 0) ? DEV_NO_RS485B : DEV_NO_RS232;
	int ret = HwOpen(iNo, &tHandle1);
	if (ret < 0)
	{
		debug_error("HwOpen() < 0\n");
		// return -1;
		goto error_exit;
	}

	while (1)
	{
		memset(buffer, 0, sizeof(buffer));
		ret = HwRead(iNo, null, buffer, sizeof(buffer)); //阻塞,等待gpio中断
		if (ret <= 0)
		{ // error
			continue;
		}

		/* 此时表示已经监听到中断触发了 */
		for (size_t i = 0; i < ret; i++)
		{
			printf("%s", buffer);
		}
		printf("\n");
	}

error_exit:
	HwClose(iNo, &tHandle1);
	pthread_exit(NULL);
}



// --------------- 测试: gpio中断 + spi读取 --------------
int AppRs232Start(int argc, char *argv[])
{


	if (argc < 5)
	{
		usage(argv[0]);
		return -1;
	}
	else if (0 == strcmp(argv[1],  "wr"))
	{
		if (argc < 6)
		{
			usage(argv[0]);
			return -1;
		}

		int iNo; // DEV_NO_RS485B : DEV_NO_RS232;
		int channel = atoi(argv[2]);
		int bandrate = atoi(argv[3]);
		int stopbit = atoi(argv[4]);
		tHandle1.iBandrate = bandrate;
		tHandle1.iStopBit = stopbit;

		if (1 == (channel & 1))
		{
			iNo = DEV_NO_RS485B;
			int ret = HwOpen(iNo, &tHandle1);
			if (ret == -1)
		    {
		        debug_error("HwOpen() < 0\n");
		        return -1;
		    }
		    HwWrite(iNo, null, argv[5], strlen(argv[5]));
			HwClose(iNo, &tHandle1);
		}
		if(2 == (channel & 2))
		{
			iNo = DEV_NO_RS232;
			int ret = HwOpen(iNo, &tHandle1);
			if (ret == -1)
		    {
		        debug_error("HwOpen() < 0\n");
		        return -1;
		    }
		    HwWrite(iNo, null, argv[5], strlen(argv[5]));
			HwClose(iNo, &tHandle1);
		}
	}
	else if (0 == strcmp(argv[1],  "rd"))
	{
		int channel = atoi(argv[2]);
		int bandrate = atoi(argv[3]);
		int stopbit = atoi(argv[4]);
		tHandle1.iBandrate = bandrate;
		tHandle1.iStopBit = stopbit;

		if (1 == (channel & 1))
		{
			static pthread_t iTid;
			int ret = pthread_create(&iTid, NULL, UartRecvTask, (void*)0);
			if (0 != ret)
			{
				printf("pthread_create() %s\n", strerror(errno));
				return -1;
			}
		}
		if (2 == (channel & 2))
		{
			static pthread_t iTid;
			int ret = pthread_create(&iTid, NULL, UartRecvTask, (void*)1);
			if (0 != ret)
			{
				printf("pthread_create() %s\n", strerror(errno));
				return -1;
			}
		}

		while(1)
		{
			char key = getchar();
			if ((key == 'q') || (key == 'Q'))
			{
			    exit(0);
			}
			pause();
		}
	}
	return 0;
}
#endif

// 初始化app RS232模块
int AppRs232Init(int argc, char *argv[])
{
	return 0;
}

